package cn.edu.nju.software.zp13.client.assignment4.sax;

import java.io.IOException;
import java.io.InputStream;
import java.util.function.Predicate;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import cn.edu.nju.software.zp13.client.assignment3.xmlNodeEntity.CourseScore;
import cn.edu.nju.software.zp13.client.assignment3.xmlNodeEntity.Score;
import cn.edu.nju.software.zp13.client.assignment3.xmlNodeEntity.util.ScoreType;
import cn.edu.nju.software.zp13.client.assignment4.sax.util.Collector;

/**
 * This class is to collect scoreList which meet the given criteria from a
 * scoreListXmlFile.
 * 
 * @author Ivan
 */
public class CourseScoreSelector extends DefaultHandler {
	private String previousTag;
	private CourseScore courseScore;
	private Score score;
	private Collector<CourseScore> courseScoreCollector;

	public CourseScoreSelector() {
		courseScoreCollector = new Collector<>();
	}

	/**
	 * return scoreList which meet the given criteria from a scoreListXmlFile.
	 * 
	 * @param selectionCriteria
	 *            the given criteria.
	 * @param sourceXmlFilePath
	 *            .
	 * @return CourseScore[] courseScore meeting the given criteria.
	 */
	public CourseScore[] selectRequiredCourseScore(Predicate<CourseScore> selectionCriteria, String xmlFilePath) {
		courseScoreCollector.setCollectCriteria(selectionCriteria);
		SAXParserFactory parserFactory = SAXParserFactory.newInstance();
		try {
			SAXParser parser = parserFactory.newSAXParser();
			parser.parse(xmlFilePath, this);
		} catch (ParserConfigurationException | SAXException | IOException e) {
			e.printStackTrace();
		}
		return courseScoreCollector.toArray(new CourseScore[courseScoreCollector.size()]);
	}

	public CourseScore[] selectRequiredCourseScore(Predicate<CourseScore> selectionCriteria, InputStream inputStream) {
		courseScoreCollector.setCollectCriteria(selectionCriteria);
		SAXParserFactory parserFactory = SAXParserFactory.newInstance();
		try {
			SAXParser parser = parserFactory.newSAXParser();
			parser.parse(inputStream, this);
		} catch (ParserConfigurationException | SAXException | IOException e) {
			e.printStackTrace();
		}
		return courseScoreCollector.toArray(new CourseScore[courseScoreCollector.size()]);
	}

	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		previousTag = qName;
		if ("课程成绩".equals(qName) && courseScore == null) {
			courseScore = new CourseScore();
			courseScore.setSt(ScoreType.valueOf(attributes.getValue(0)));
			courseScore.setCourseId(attributes.getValue(1));
		} else if ("成绩".equals(qName)) {
			score = new Score();
		}
	}

	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		previousTag = null;
		if ("课程成绩".equals(qName) && courseScore != null) {
			courseScore = null;
		} else if ("成绩".equals(qName)) {
			courseScore.setScore(score);
			// collect courseScore
			try {
				courseScoreCollector.collect(courseScore.clone());
			} catch (CloneNotSupportedException e) {
				e.printStackTrace();
			}
			score = null;
		}
	}

	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		String text = new String(ch, start, length);
		if ("学号".equals(previousTag)) {
			if (score != null) {
				score.setStudentId(text);
			}
		} else if ("得分".equals(previousTag)) {
			if (score != null) {
				score.setScore(Integer.parseInt(text));
			}
		}
	}
}
